#include "capture.h"

Capture::Capture()
{

}

Capture::~Capture()
{
    if (bOpenSuccess)
        GXCloseDevice(hDevice);
}
bool Capture::openCapture(int nID)
{
    //English: if we want to open a capture that drived by windows drives,
    //          we can use cv::VideoCapture do it directly,else,if we use another
    //          captures such as Daheng Cameras,we need to add their own SDK
    //          functions.
    //Chinese:( Encode UTF-8)如果是打开一个标准的Windows驱动的摄像头，直接使用
    //          cv::VideoCapture类打开，如果我们使用别的摄像头，如大恒的摄像头，
    //          那么我们就需要使用他们提供的SDK进行操作。
    /*           Use Standard Windows Driver's Capture Operations
     *           使用标准Windows驱动的相机操作：
                 bool  openCapture (int nID)
                 {
                    cv::VideoCapture cap;
                    bool bSuccess = cap.open(nID);
                    return bSuccess;
                 }
    */
    hDevice = NULL;
    GX_STATUS status = GX_STATUS_SUCCESS;
    GX_OPEN_PARAM stOpenParam;

    char dev[2];
    switch (nID)
    {
    case 0:
        strcpy (dev,"1");break;
    case 1:
        strcpy (dev,"2");break;
    default:
        strcpy (dev,"1");break;
    }
    uint32_t nDeviceNum;
    status = GXUpdateDeviceList(&nDeviceNum, 1000);
    if (nDeviceNum <= 0)
        return NO_CAPTURE;
    //打开设备
    stOpenParam.accessMode = GX_ACCESS_EXCLUSIVE;
    stOpenParam.openMode   = GX_OPEN_INDEX;
    stOpenParam.pszContent = dev;
    status = GXOpenDevice(&stOpenParam, &hDevice);

    if (status == GX_STATUS_SUCCESS)
    {
        bOpenSuccess = true;
        return OPEN_SUCCESS;
    }
    else
    {
        bOpenSuccess = OPEN_FAILED;
        return false;
    }
}

void Capture::closeCapture()
{
    if (bOpenSuccess)
        GXCloseDevice(hDevice);
    bOpenSuccess = false;
}

void Capture::stopCapture()
{
    stop = true;
}

void Capture::run()
{
    cv::Mat dst;
    stop = false;

    int64_t height,width;
    //English:get image size: width
    //Chinese:( Encode UTF-8)获取图片宽度
    GXGetInt(hDevice, GX_INT_WIDTH, &width);
    //English:get image size:height
    //Chinese:( Encode UTF-8)获得图片高度
    GXGetInt(hDevice, GX_INT_HEIGHT, &height);
    //English:create a Mat structure and the size mast be same as captured image.
    //Chinese:( Encode UTF-8)创建相同大小的目标Mat变量
    dst.create(height,width,CV_8U);

    int64_t nPayLoadSize = 0;
    //English: get image payloads,use for malloc memory
    //Chinese:( Encode UTF-8)获取图片数据所需空间大小，用于分配内存
    GX_STATUS status = GXGetInt(hDevice, GX_INT_PAYLOAD_SIZE, &nPayLoadSize);
    if (status == GX_STATUS_SUCCESS && nPayLoadSize > 0)
    {
        //English: a parametor that belongs to GXGetImage
        //Chinese:( Encode UTF-8)定义GXGetImage的传入参数
        GX_FRAME_DATA stFrameData;

        //根据获取的图像buffer大小m_nPayLoadSize申请buffer
        stFrameData.pImgBuf     = malloc((size_t)nPayLoadSize);

        //English: make the pointer points to dst.data
        //Chinese:( Encode UTF-8)让dst.data指针指向stFrameData.pImgBuf
        dst.data =(uchar *) stFrameData.pImgBuf;

        //English: Send the command of capturing images
        //Chinese:( Encode UTF-8)发送开始采集命令
        status = GXSendCommand(hDevice, GX_COMMAND_ACQUISITION_START);
        if (status == GX_STATUS_SUCCESS)
        {
            //English: use the function GXGetImage to get a image
            //Chinese:( Encode UTF-8)调用GXGetImage取一帧图像
            while (!stop)
            {

                if(getAImageFromCapture (stFrameData))
                //English:emit the signal which contains the image we getted,
                //        becase of we did the:dst.data =(uchar *) stFrameData.pImgBuf,
                //        so,when we execute :GXGetImage(hDevice,&stFrameData, 100)
                //        ,we can get the latest messages in dst(Mat Structure)
                //Chinese:( Encode UTF-8)作为Qt信号，发送捕获到的Mat结构体，因为上面
                //          我们执行了：dst.data =(uchar *) stFrameData.pImgBuf
                //          每次执行：GXGetImage(hDevice,&stFrameData, 100)
                //          都会让最新的数据保存在：stFrameData.pImgBuf中，
                //          也就是说，dst.data指向的数据时刻更新的，所以直接使用
                //          emit sendFrame(dst)就可以把图像发出去
                    emit sendMat(dst);
                else
                    Sleep(30);
            }
            //English: send the command of stop capturing
            //Chinese:( Encode UTF-8)发送停止采集命令
            status = GXSendCommand(hDevice, GX_COMMAND_ACQUISITION_STOP);
            //释放图像缓冲区buffer
            free(stFrameData.pImgBuf);
        }
    }
}

//**************************************************
// Function  : getAImageFromCapture;
// Parameter : GX_FRAME_DATA &inStFrameData
//
// Return    : Success 1 / Failed 0
//
// Description: get a image form the capture
//
//**************************************************
bool Capture::getAImageFromCapture(GX_FRAME_DATA &inStFrameData)
{
    //English:
    //Chinese:( Encode UTF-8) count是为了防止死循环而进行的防止超时响应处理
    int count = 0;
    while(GXGetImage(hDevice,&inStFrameData, 100) != GX_STATUS_SUCCESS &&
          count < 100)
    {
        count++;
        Sleep(10);
    }
    //English: if GXGetImage did success
    //Chinese:( Encode UTF-8)如果函数执行成功，获取到了图像
    if (inStFrameData.nStatus == 0)
        return true;
    else
        return false;
}
